﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint.LookupPicker (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.SharePoint;

namespace Sapiens.at.SharePoint.Fields
{
    /// <summary>
    /// Represents the properties of the lookup picker field.
    /// </summary>
    [Serializable]
    public class LookupPickerData : ISerializable
    {
        Guid _webID = Guid.Empty;
        Guid _listID = Guid.Empty;
        string[] _additionalSearchFields = null;
        string[] _additionalDisplayFields = null;
        string _lookupField = null;        
        string _idFieldName;
        string[] _allDisplayFields = null;
        string[] _allSearchFields = null;
        bool _allowMultiValue = false;
        bool _allowShowAll = true;
        string[] _contentTypes;
        string _searchScope;

        /// <summary>
        /// Gets a collection of all fields that are shown in the <see cref="LookupPickerDialog"/> results table.
        /// </summary>
        public string[] AllDisplayFields
        {
            get
            {
                if (_allDisplayFields == null)
                {
                    var list = new List<string>(_additionalDisplayFields);
                    list.Insert(0, _lookupField);
                    _allDisplayFields = list.ToArray();
                }
                return _allDisplayFields;
            }
        }

        /// <summary>
        /// Gets a collection of all fields that will be searched.
        /// </summary>
        public string[] AllSearchFields
        {
            get
            {
                if (_allSearchFields == null)
                {
                    var list = new List<string>(_additionalSearchFields);
                    list.Insert(0, _lookupField);
                    _allSearchFields = list.ToArray();
                }
                return _allSearchFields;
            }
        }

        /// <summary>
        /// Gets the name of the field that stores the id. Usually "ID".
        /// </summary>
        public string IDFieldName
        {
            get { return _idFieldName; }
        }

        /// <summary>
        /// Gets the name of the field that the lookuppicker shows in its textbox.
        /// </summary>
        public string LookupField
        {
            get { return _lookupField; }
        }

        /// <summary>
        /// Gets a collection of fields that will be searched additionally to the <see cref="LookupField"/>.
        /// </summary>
        /// <seealso cref="AllSearchFields"/>
        public string[] AdditionalSearchFields
        {
            get { return _additionalSearchFields; }
        }

        /// <summary>
        /// Gets a collection of fields that will be shown additionally to the <see cref="LookupField"/>.
        /// </summary>
        /// <seealso cref="AllDisplayFields"/>
        public string[] AdditionalDisplayFields
        {
            get { return _additionalDisplayFields; }
        }

        /// <summary>
        /// Gets the id of the web the lookup list is in.
        /// </summary>
        public Guid WebID
        {
            get { return _webID; }
        }

        /// <summary>
        /// Gets the id of the list the lookup points to.
        /// </summary>
        public Guid ListID
        {
            get { return _listID; }
        }

        /// <summary>
        /// Returns true if the field can contain multiple values to different listitems in the lookup list.
        /// </summary>
        public bool AllowMultiValue
        {
            get { return _allowMultiValue; }
        }

        /// <summary>
        /// Returns true if the user can execute the search without any search string to get all available listitems.
        /// </summary>
        public bool AllowShowAll
        {
            get { return _allowShowAll; }
        }

        /// <summary>
        /// Gets a collection of contenttype ids that will be searched for.
        /// </summary>
        public string[] ContentTypes
        {
            get { return _contentTypes; }
        }

        /// <summary>
        /// Gets the scope that will be used for the search.
        /// </summary>
        public string SearchScope
        {
            get { return _searchScope; }
        }

        /// <summary>
        /// Instantiates a new properties container for a lookuppicker.
        /// </summary>
        /// <param name="webID">the id of the web the lookup list is in</param>
        /// <param name="listID">the id of the list the lookup points to</param>
        /// <param name="lookupField">the name of the field that the lookuppicker shows in its textbox</param>
        /// <param name="additionalSearchFields">a collection of fields that will be searched additionally to the <see cref="LookupField"/></param>
        /// <param name="additionalDisplayFields">a collection of fields that will be shown additionally to the <see cref="LookupField"/></param>
        /// <param name="idFieldName">the name of the field that stores the id. Usually "ID"</param>
        /// <param name="allowMultiValue">true if the field can contain multiple values to different listitems in the lookup list</param>
        /// <param name="allowShowAll">true if the user can execute the search without any search string to get all available listitems</param>
        /// <param name="contentTypes">a collection of contenttype ids that will be searched for</param>
        /// <param name="searchScope">the scope that will be used for the search</param>
        public LookupPickerData(Guid webID, Guid listID, string lookupField, string[] additionalSearchFields, string[] additionalDisplayFields, string idFieldName, bool allowMultiValue, bool allowShowAll, string[] contentTypes, string searchScope)
        {
            _webID = webID;
            _listID = listID;
            _lookupField = lookupField;
            _additionalSearchFields = additionalSearchFields;
            _additionalDisplayFields = additionalDisplayFields;
            _idFieldName = idFieldName;
            _allowMultiValue = allowMultiValue;
            _allowShowAll = allowShowAll;
            _contentTypes = contentTypes;
            _searchScope = searchScope;
        }

        /// <summary>
        /// Deserializes a lookuppickerdata.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        protected LookupPickerData(SerializationInfo info, StreamingContext context)
        {
            _webID = (Guid)info.GetValue("WebID", typeof(Guid));
            _listID = (Guid)info.GetValue("ListID", typeof(Guid));
            _lookupField = info.GetString("LookupField");
            _additionalSearchFields = (string[])info.GetValue("AdditionalSearchFields", typeof(string[]));
            _additionalDisplayFields = (string[])info.GetValue("AdditionalDisplayFields", typeof(string[]));
            _idFieldName = info.GetString("IDField");
            _allowMultiValue = info.GetBoolean("AllowMultiValue");
            _allowShowAll = info.GetBoolean("AllowShowAll");
            _contentTypes = (string[])info.GetValue("ContentTypes", typeof(string[]));
            _searchScope = info.GetString("SearchScope");
        }

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("WebID", _webID);
            info.AddValue("ListID", _listID);
            info.AddValue("LookupField", _lookupField);
            info.AddValue("AdditionalSearchFields", _additionalSearchFields);
            info.AddValue("AdditionalDisplayFields", _additionalDisplayFields);
            info.AddValue("IDField", _idFieldName);
            info.AddValue("AllowMultiValue", _allowMultiValue);
            info.AddValue("AllowShowAll", _allowShowAll);
            info.AddValue("ContentTypes", _contentTypes);
            info.AddValue("SearchScope", _searchScope);
        }

        /// <summary>
        /// Serializes the pickerData.
        /// </summary>
        /// <param name="pickerData"></param>
        /// <returns></returns>
        public static string Serialize(LookupPickerData pickerData)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, pickerData);
                return Convert.ToBase64String(stream.ToArray());
            }
        }

        /// <summary>
        /// Deserializes the customProperty.
        /// </summary>
        /// <param name="customProperty"></param>
        /// <returns></returns>
        public static LookupPickerData Deserialize(string customProperty)
        {
            LookupPickerData result = null;
            if (!String.IsNullOrEmpty(customProperty))
            {
                byte[] buffer = Convert.FromBase64String(customProperty);
                using (MemoryStream stream = new MemoryStream(buffer))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    result = (LookupPickerData)formatter.Deserialize(stream);
                }
            }
            return result;
        }

        /// <summary>
        /// Returns a collection of <see cref="SPContentType"/>s for this contenttype ids.
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public SPContentType[] GetContentTypes(SPList list)
        {
            return GetContentTypes(list, ContentTypes);
        }

        /// <summary>
        /// Returns a collection of <see cref="SPContentType"/>s for a collection of contenttype ids.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="contentTypes"></param>
        /// <returns></returns>
        public static SPContentType[] GetContentTypes(SPList list, string[] contentTypes)
        {
            var result = new List<SPContentType>();
            foreach (string ctype in contentTypes)
            {
                if (ctype.StartsWith("0x01"))
                {
                    result.Add(list.ContentTypes[list.ContentTypes.BestMatch(new SPContentTypeId(ctype))]);
                }
                else
                {
                    result.Add(list.ContentTypes[ctype]);
                }
            }
            return result.ToArray();
        }
    }
}
